<?php
namespace App\Models\System;

use App\Exceptions\ApiException;
use App\Providers\LengthAwarePaginatorProvider;
use Carbon\Carbon;
use hisorange\BrowserDetect\Parser as Browser;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use ruoyi\admin\constant\Constants;
use ruoyi\admin\Utils;
use App\Enums\System\SysLogininfor\{Status};

/**
* 系统访问记录 模型
* @create 2023-08-22 10:02:51
*/
class SysLogininforModel extends \App\Models\BaseModel {
    use HasFactory;

    const Table         = "sys_logininfor";
    const PrimaryKey    = "info_id";
    public $timestamps  = false;

    static $Wheres = ['info_id','status'];     // 直接定义column, 默认where(column, '=', value)
    public function __construct($attributes = []) {
        parent::__construct($attributes);

        // static::$Wheres['info_id']   = fn($q, $v) => $q->where(atn('info_id'), '=', $v);
        static::$Wheres['ipaddr']       = fn($q, $v) => $q->where(atn('ipaddr'), 'like', "%{$v}%");
        static::$Wheres['user_name']    = fn($q, $v) => $q->where(atn('user_name'), 'like', "%{$v}%");
        static::$Wheres['begin_time']   = fn($q, $v) => $q->whereDate(atn('create_time'), '>=', $v);    // ymd
        static::$Wheres['end_time']     = fn($q, $v) => $q->whereDate(atn('create_time'), '<=', $v);    // ymd
    }

    /** xxxx */
    // public function user() {
        // return $this->hasOne(User::class, 'id', 'uid');
    // }

    protected $fillable = ['user_name','ipaddr','login_location','browser','os','status','msg','login_time',];

    public function recordLogininfor($username, string $status, string $msg) {
        $success = [Constants::LOGIN_SUCCESS, Constants::LOGOUT, Constants::REGISTER,]; // Constants::LOGIN_FAIL
        $ip = request()->ip();
        $addr = Utils::getRealAddressByIP($ip);         // todo 获取真实地址, 异步处理更好
       $this->create([
            'user_name'         => $username,
            'ipaddr'            => $ip,
            'login_location'    => $addr,
            'browser'           => Browser::browserName(),
            'os'                => Browser::platformName(),
            'status'            => in_array($status, $success) ? Constants::SUCCESS : Constants::FAIL,
            'msg'               => $msg,
            'login_time'        => now()->toDateTimeString(),
        ]);
    }

    /** ========== 常用查询 ========== */
    static $Vo = ['info_id','user_name','status','ipaddr','login_location','browser','os','msg','login_time'];
    static $Voi = ['*', ];


    /**
     * 新增系统登录日志
     * 
     * @param $logininfor 访问日志对象
     */
    public function insertLogininfor(array $logininfor): SysLogininforModel {
        $values = static::when(
                    $logininfor,
                    'user_name',
                    'status',
                    'ipaddr',
                    'login_location',
                    'browser',
                    'os',
                    'msg',
                );
        $values['login_time'] = Carbon::now();
        return throw_str(static::row_add($values));
    }

    /**
     * 查询系统登录日志集合
     * 
     * @param $logininfor 访问日志对象
     * @return SysLogininforModel[]|Collection 登录记录集合
     */
    public function selectLogininforList(array $logininfor): Collection {
        return $this->selectVo()
            ->wheres($logininfor, 'ipaddr'. 'status', 'user_name', 'begin_time', 'end_time')
            ->get()
            ;
    }

    /**
     * 批量删除系统登录日志
     * 
     * @param $infoIds 需要删除的登录日志ID
     * @return 结果
     */
    public function deleteLogininforByIds(array $infoIds): int {
        return $this
            ->whereIn('info_id', $infoIds)
            ->delete()
            ;
    }

    /**
     * 清空系统登录日志
     * 
     * @return 结果
     */
    public function cleanLogininfor(): int {
        return $this
            ->truncate()
            ;
    }

    /** 根据InfoId获取 */
    public function selectByInfoId($info_id): SysLogininforModel {
        $where = [['info_id', '=', "{$info_id}"]];
        return throw_str(
            static::row($where) ?? "数据($info_id)为空~"
        );
    }


    /** 获取列表 @return SysLogininfor[]+paginator() */
    public function selectList(int|array $pag=1, array $param=[]): LengthAwarePaginatorProvider {
        return static::rows_pag($pag, [], fn($q)=>$q
                    // ->when(isset($param['info_id']), fn($q)=>$q->where('info_id', '=', $param['info_id']))
                    ->wheres($param, 'info_id','status')
                    ->orderByDesc("info_id")
        );
    }


    /** 插入数据 */
    public function insertData(array $data): SysLogininforModel {
        return throw_str(
            static::row_add([
                // 'info_id'        => $data['info_id'],
                'user_name'         => $data['user_name'] ?? '',
                'ipaddr'            => $data['ipaddr'] ?? '',
                'login_location'    => $data['login_location'] ?? '',
                'browser'           => $data['browser'] ?? '',
                'os'                => $data['os'] ?? '',
                'status'            => $data['status'] ?? '0',
                'msg'               => $data['msg'] ?? '',
                'login_time'        => $data['login_time'] ?? '',
            ])
        );
    }


    /** 更新数据 */
    public function updateData(int|array $idOrWhere, array $data): SysLogininforModel {
        $values = static::when(
                    $data, 
                    // 'info_id',
                    'user_name',
                    'ipaddr',
                    'login_location',
                    'browser',
                    'os',
                    'status',
                    'msg',
                    'login_time',
                );
        return throw_str(
            static::row_update($idOrWhere, $values)
        );
    }


    /** 删除数据 */
    public function deleteData(int|array $idOrWhere): SysLogininforModel {
        return throw_str(
            static::row_delete($idOrWhere)
        );
    }



}